﻿using System;
using System.Collections;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using System.Drawing;

namespace DirectXSim
{
    public class Track
    {

        private float[] _buildingheights = new float[] { 0.0f, 0.5f, 1f, 2f, 2f };
        private int[,] _raceTrack;
        private int _WIDTH;
        private int _HEIGHT;
        private int _differentbuildings = 2;

        private CustomVertex.PositionNormalTextured[] _verticesarray;
        ArrayList _verticeslist = new ArrayList();

        private int _maxItems = 40;
        private ArrayList _itemList = new ArrayList();

        public CustomVertex.PositionNormalTextured[] VerticesArray
        {
            get { return _verticesarray; }
        }

        public int PrimitiveCount
        {
            get { return _verticeslist.Count / 3; }
        }

        public Track(ref Device dev)
        {
            //Load track
            _WIDTH = 10;
            _HEIGHT = 250;

            _raceTrack = new int[_WIDTH, _HEIGHT];

            Random random = new Random();

            //Create obstacles - one at each row, at a random column
            for (int y = 10; y < _HEIGHT; y++)
            {
                //Barriers at both sides of track
                _raceTrack[0, y] = 1;
                _raceTrack[_WIDTH - 1, y] = 1;

                if (y % 5 == 0)
                {
                    //Random Obstacle
                    int x = random.Next(_WIDTH - 2) + 1;

                    _raceTrack[x, y] = random.Next(3) + 2;
                }
            }

            VertexDeclaration();

            //Load Bonus Items
            AddBonusItems(ref dev);
        }

        public ArrayList BonusItemList
        {
            get { return _itemList; }
        }


        private void AddBonusItems(ref Device dev)
        {
            //Add bonus items
            while (_itemList.Count < _maxItems)
            {
                Random random = new Random();
                int x = random.Next(_WIDTH);
                int y = random.Next(_HEIGHT);

                bool acceptableposition = true;
                if (_raceTrack[x, y] > 0)
                {
                    acceptableposition = false;
                }
                foreach (BonusItem currentItem in _itemList)
                {
                    if (((int)currentItem.Position.X == x) && ((int)currentItem.Position.Y == y))
                    {
                        acceptableposition = false;
                    }
                }

                if (acceptableposition == true)
                {
                    Vector3 pos = new Vector3(x + 0.5f, y + 0.5f, 0.2f);

                    Material newmaterial = new Material();
                    newmaterial.Diffuse = Color.FromArgb(random.Next(255), random.Next(255), random.Next(255));
                    newmaterial.Ambient = Color.FromArgb(random.Next(255), random.Next(255), random.Next(255));

                    ItemType bonusType = (ItemType)random.Next(1, 5);

                    BonusItem newItem = new BonusItem(pos, newmaterial, bonusType, ref dev);

                    _itemList.Add(newItem);
                }
            }
        }

        public int Width
        {
            get { return _WIDTH; }
        }

        public int Height
        {
            get { return _HEIGHT; }
        }

        public CollisionType CheckTrackCollision(Vector3 position, float radius)
        {

            //Check against barrier of track
            if ((position.X < 1) || (position.X > _WIDTH - 1))
            {
                return CollisionType.Barrier;
            }

            //Check if reached end of track
            if ((position.Y <= -1) || (position.Y > _HEIGHT))
            {
                return CollisionType.EndTrack;
            }

            //Check against obstacles
            if (_raceTrack[(int)position.X, (int)position.Y] > 0)
            {
                return CollisionType.Obstacle;
            }

            return CollisionType.None;
        }

        public ItemType CheckBonusItemPickup(Vector3 position, float radius)
        {
            //Check if we are on a pick-up
            for (int i = 0; i < _itemList.Count; i++)
            {
                BonusItem currentItem = (BonusItem)_itemList[i];
                if (Math.Sqrt(Math.Pow(currentItem.Position.X - position.X, 2) + Math.Pow(currentItem.Position.Y - position.Y, 2) + Math.Pow(currentItem.Position.Z - position.Z, 2)) < radius + currentItem.Radius)
                {
                    //Remove from list of pickups
                    _itemList.RemoveAt(i);
                    return currentItem.Type;
                }
            }
            return ItemType.None;
        }

        public void VertexDeclaration()
        {
            float imagesintexture = 1 + _differentbuildings * 2;

            Random r = new Random();


            //U,V map
            //[1,0][0,0]
            //[1,1][0,1]

            for (int x = 0; x < _WIDTH; x++)
            {
                for (int y = 0; y < _HEIGHT; y++)
                {
                    float xval = 0.0f;// (float)r.NextDouble();
                    float yval = 0.0f;// (float)r.NextDouble();
                    int currentbuilding = _raceTrack[x, y];

                    _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x, y, _buildingheights[currentbuilding]), new Vector3(0, 0, 1), (currentbuilding * 2 + 1) / imagesintexture, 1));
                    _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x + 1, y, _buildingheights[currentbuilding]), new Vector3(0, 0, 1), currentbuilding * 2 / imagesintexture, 1));
                    _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x + 1, y + 1, _buildingheights[currentbuilding]), new Vector3(0, 0, 1), currentbuilding * 2 / imagesintexture, 0));

                    _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x + 1, y + 1, _buildingheights[currentbuilding]), new Vector3(0, 0, 1), currentbuilding * 2 / imagesintexture, 0));
                    _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x, y + 1, _buildingheights[currentbuilding]), new Vector3(0, 0, 1), (currentbuilding * 2 + 1) / imagesintexture, 0));
                    _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x, y, _buildingheights[currentbuilding]), new Vector3(0, 0, 1), (currentbuilding * 2 + 1) / imagesintexture, 1));

                    if (y > 0)
                    {
                        if (_raceTrack[x, y - 1] != _raceTrack[x, y])
                        {
                            if (_raceTrack[x, y - 1] > 0)
                            {
                                currentbuilding = _raceTrack[x, y - 1];
                                _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x + xval, y + yval, 0f), new Vector3(0, 1, 0), (currentbuilding * 2 - 1) / imagesintexture, 1));
                                _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x + 1 + xval, y + yval, _buildingheights[currentbuilding]), new Vector3(0, 1, 0), currentbuilding * 2 / imagesintexture, 0));
                                _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x + 1 + xval, y + yval, 0f), new Vector3(0, 1, 0), currentbuilding * 2 / imagesintexture, 1));

                                _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x + 1 + xval, y + yval, _buildingheights[currentbuilding]), new Vector3(0, 1, 0), currentbuilding * 2 / imagesintexture, 0));
                                _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x + xval, y + yval, 0f), new Vector3(0, 1, 0), (currentbuilding * 2 - 1) / imagesintexture, 1));
                                _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x + xval, y + yval, _buildingheights[currentbuilding]), new Vector3(0, 1, 0), (currentbuilding * 2 - 1) / imagesintexture, 0));
                            }
                            if (_raceTrack[x, y] > 0)
                            {
                                currentbuilding = _raceTrack[x, y];
                                _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x + xval, y + yval, 0f), new Vector3(0, -1, 0), currentbuilding * 2 / imagesintexture, 1));
                                _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x + 1 + xval, y + yval, 0f), new Vector3(0, -1, 0), (currentbuilding * 2 - 1) / imagesintexture, 1));
                                _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x + 1 + xval, y + yval, _buildingheights[currentbuilding]), new Vector3(0, -1, 0), (currentbuilding * 2 - 1) / imagesintexture, 0));

                                _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x + xval, y + yval, 0f), new Vector3(0, -1, 0), currentbuilding * 2 / imagesintexture, 1));
                                _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x + 1 + xval, y + yval, _buildingheights[currentbuilding]), new Vector3(0, -1, 0), (currentbuilding * 2 - 1) / imagesintexture, 0));
                                _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x + xval, y + yval, _buildingheights[currentbuilding]), new Vector3(0, -1, 0), currentbuilding * 2 / imagesintexture, 0));
                            }
                        }
                    }
                    if (x > 0)
                    {
                        if (_raceTrack[x - 1, y] != _raceTrack[x, y])
                        {
                            if (_raceTrack[x - 1, y] > 0)
                            {
                                currentbuilding = _raceTrack[x - 1, y];
                                _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x + xval, y + yval, 0f), new Vector3(1, 0, 0), currentbuilding * 2 / imagesintexture, 1));
                                _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x + xval, y + 1 + yval, 0f), new Vector3(1, 0, 0), (currentbuilding * 2 - 1) / imagesintexture, 1));
                                _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x + xval, y + 1 + yval, _buildingheights[currentbuilding]), new Vector3(1, 0, 0), (currentbuilding * 2 - 1) / imagesintexture, 0));

                                _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x + xval, y + 1 + yval, _buildingheights[currentbuilding]), new Vector3(1, 0, 0), (currentbuilding * 2 - 1) / imagesintexture, 0));
                                _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x + xval, y + yval, _buildingheights[currentbuilding]), new Vector3(1, 0, 0), currentbuilding * 2 / imagesintexture, 0));
                                _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x + xval, y + yval, 0f), new Vector3(1, 0, 0), currentbuilding * 2 / imagesintexture, 1));
                            }
                            if (_raceTrack[x, y] > 0)
                            {
                                currentbuilding = _raceTrack[x, y];
                                _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x + xval, y + yval, 0f), new Vector3(-1, 0, 0), (currentbuilding * 2 - 1) / imagesintexture, 1));
                                _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x + xval, y + yval, _buildingheights[currentbuilding]), new Vector3(-1, 0, 0), (currentbuilding * 2 - 1) / imagesintexture, 0));
                                _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x + xval, y + 1 + yval, 0f), new Vector3(-1, 0, 0), currentbuilding * 2 / imagesintexture, 1));

                                _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x + xval, y + yval, _buildingheights[currentbuilding]), new Vector3(-1, 0, 0), (currentbuilding * 2 - 1) / imagesintexture, 0));
                                _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x + xval, y + 1 + yval, _buildingheights[currentbuilding]), new Vector3(-1, 0, 0), currentbuilding * 2 / imagesintexture, 0));
                                _verticeslist.Add(new CustomVertex.PositionNormalTextured(new Vector3(x + xval, y + 1 + yval, 0f), new Vector3(-1, 0, 0), currentbuilding * 2 / imagesintexture, 1));
                            }
                        }
                    }
                }
            }
            _verticesarray = (CustomVertex.PositionNormalTextured[])_verticeslist.ToArray(typeof(CustomVertex.PositionNormalTextured));
        }
    }
}
